package web.suzy.oj.manager.oj;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import web.suzy.oj.dao.problem.*;
import web.suzy.oj.pojo.entity.problem.*;
import web.suzy.oj.pojo.vo.CaptchaVO;
import web.suzy.oj.pojo.vo.ProblemTagVO;
import web.suzy.oj.utils.RedisUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * YangSuzy 软件工作室
 * 类名: CommonManager
 * 描述: 常用方法管理器
 * 功能: ---- 待定 -----
 * =========未完成============
 *
 * @author YangSuzy
 * Date: 2022/11/14 12:43
 */
@Component
public class CommonManager {

    @Autowired
    private TagEntityService tagEntityService;

    @Autowired
    private TagClassificationEntityService tagClassificationEntityService;

    @Autowired
    private ProblemTagEntityService problemTagEntityService;

    @Autowired
    private ProblemLanguageEntityService problemLanguageEntityService;

    @Autowired
    private LanguageEntityService languageEntityService;

    @Autowired
    private CodeTemplateEntityService codeTemplateEntityService;

    @Autowired
    private RedisUtils redisUtil;

    /**
     * 方法名: getCaptcha
     * 描述: 获取验证码
     *
     * @return web.suzy.oj.pojo.vo.CaptchaVO
     * @date 2022/11/14 12:45
     * @auther YangSuzy
     **/
    public CaptchaVO getCaptcha() {
        //生成验证码图片
        ArithmeticCaptcha specCaptcha = new ArithmeticCaptcha(90, 30, 4);
        //设置数字和字母混合
        specCaptcha.setCharType(Captcha.TYPE_DEFAULT);
        //2位数运算
        specCaptcha.setLen(2);
        //获取验证码文本
        String verCode = specCaptcha.text().toLowerCase();
        //设置验证码uuid
        String key = IdUtil.simpleUUID();
        //存入redis并设置过期时间为30分钟
        redisUtil.set(key, verCode, 1800);
        //将key和base64返回给前端
        CaptchaVO captchaVo = new CaptchaVO();
        captchaVo.setImg(specCaptcha.toBase64());
        captchaVo.setCaptchaKey(key);
        return captchaVo;
    }

    /**
     * 方法名: getProblemTagsAndClassification
     * 描述: 获取题目标签和标签分类
     *
     * @return java.util.List<web.suzy.oj.pojo.vo.ProblemTagVO>
     * @date 2022/12/11 16:01
     * @auther YangSuzy
     **/
    public List<ProblemTagVO> getProblemTagsAndClassification() {
        List<ProblemTagVO> problemTagVOList = new ArrayList<>();
        //获取所有标签和标签分类
        List<Tag> tagList = tagEntityService.list();
        List<TagClassification> classificationList = tagClassificationEntityService.list();

        if (CollectionUtils.isEmpty(classificationList)) {
            //分类为空时直接保存标签
            ProblemTagVO problemTagVo = new ProblemTagVO();
            problemTagVo.setTagList(tagList);
            problemTagVOList.add(problemTagVo);
        } else {
            //有分类时要判断分类下的标签
            for (TagClassification classification : classificationList) {
                ProblemTagVO problemTagVo = new ProblemTagVO();
                problemTagVo.setClassification(classification);
                List<Tag> tags = new ArrayList<>();
                if (!CollectionUtils.isEmpty(tagList)) {
                    Iterator<Tag> it = tagList.iterator();
                    while (it.hasNext()) {
                        Tag tag = it.next();
                        if (classification.getId().equals(tag.getTcid())) {
                            tags.add(tag);
                            it.remove();
                        }
                    }
                }
                problemTagVo.setTagList(tags);
                problemTagVOList.add(problemTagVo);
            }
            if (tagList.size() > 0) {
                ProblemTagVO problemTagVo = new ProblemTagVO();
                problemTagVo.setTagList(tagList);
                problemTagVOList.add(problemTagVo);
            }
        }
        //根据标签分类的优先级对题目标签视图对象列表进行排序
        Collections.sort(problemTagVOList, problemTagVoComparator);
        return problemTagVOList;
    }

    /**
     * 比较器，根据标签分类的优先级对题目标签视图对象列表进行排序
     */
    private final Comparator<ProblemTagVO> problemTagVoComparator = (p1, p2) -> {
        if (p1 == null) {
            return 1;
        }
        if (p2 == null) {
            return 1;
        }
        if (p1.getClassification() == null) {
            return 1;
        }
        if (p2.getClassification() == null) {
            return -1;
        }
        TagClassification p1Classification = p1.getClassification();
        TagClassification p2Classification = p2.getClassification();
        return p1Classification.getRank().compareTo(p2Classification.getRank());
    };

    /**
     * 方法名: getAllProblemTagsList
     * 描述: 获取所有标签列表
     *
     * @return java.util.List<web.suzy.oj.pojo.entity.problem.Tag>
     * @date 2022/12/11 20:29
     * @auther YangSuzy
     **/
    public List<Tag> getAllProblemTagsList() {
        return tagEntityService.list();
    }

    /**
     * 方法名: getProblemTags
     * 描述: 根据题目ID获取题目标签
     *
     * @param pid 题目ID
     * @return java.util.Collection<web.suzy.oj.pojo.entity.problem.Tag>
     * @date 2022/12/11 20:54
     * @auther YangSuzy
     **/
    public Collection<Tag> getProblemTags(Long pid) {
        Map<String, Object> map = new HashMap<>();
        map.put("pid", pid);
        List<Long> tidList = problemTagEntityService.listByMap(map)
                .stream()
                .map(ProblemTag::getTid)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(tidList)) {
            return new ArrayList<>();
        }
        return tagEntityService.listByIds(tidList);
    }

    /**
     * 方法名: getLanguages
     * 描述: 获取所有编程语言
     *
     * @return java.util.List<web.suzy.oj.pojo.entity.problem.Language>
     * @date 2022/12/11 21:06
     * @auther YangSuzy
     **/
    public List<Language> getLanguages() {
        return languageEntityService.list();
    }

    /**
     * 方法名: getProblemLanguages
     * 描述: 根据题目ID获取题目支持的语言
     *
     * @param pid 题目ID
     * @return java.util.Collection<web.suzy.oj.pojo.entity.problem.Language>
     * @date 2022/12/11 21:40
     * @auther YangSuzy
     **/
    public Collection<Language> getProblemLanguages(Long pid) {
        QueryWrapper<ProblemLanguage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", pid).select("lid");
        List<Long> idList = problemLanguageEntityService.list(queryWrapper)
                .stream().map(ProblemLanguage::getLid).collect(Collectors.toList());
        return languageEntityService.listByIds(idList);
    }

    /**
     * 方法名: getProblemCodeTemplate
     * 描述: 根据题目ID获取题目代码模板
     *
     * @param pid
     * @return java.util.List<web.suzy.oj.pojo.entity.problem.CodeTemplate>
     * @date 2022/12/11 21:57
     * @auther YangSuzy
     **/
    public List<CodeTemplate> getProblemCodeTemplate(Long pid) {
        QueryWrapper<CodeTemplate> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", pid);
        return codeTemplateEntityService.list(queryWrapper);
    }
}
